/**
 * @file    drv_gpio.h
 * @author  yhy
 * @brief   芯必达IM94x系列芯片, GPIP抽象层
 * @version 1.01
 * @date    2025-07-02
 *
 * @copyright Copyright (c) 2025
 *
 * @details
 * Change Logs:
 * Date           Author       Notes
 * 2025-07-02     yhy          the first version V1.00
 * 2025-07-11     yhy          1. 所有函数和变量名修改为snf_开头 V1.01
 *                             2. 增加了引脚初始电平配置项
 *
 */
#ifndef __DRV_GPIO_H__
#define __DRV_GPIO_H__

#include "common_config.h"

#include <stdbool.h>
#include <stdint.h>

/* 配置参数 */
#define GPIO_PORT_MAX_COUNT 5U                                        /* GPIO端口数量 */
#define PORT_PIN_MAX_SIZE   18U                                       /* 一个端口的引脚数量 */
#define PORT_ADDR_INTERVAL  0x200U                                    /* 端口地址间隔 */
#define GPIO_MAX_PIN_NUM    (GPIO_PORT_MAX_COUNT * PORT_PIN_MAX_SIZE) /* 最大引脚编号 */
#define GPIOA_BASE_ADDR     (0x4000E000U)                             /* GPIOA基地址 */
#define GPIOB_BASE_ADDR     (0x4000E200U)                             /* GPIOB基地址 */
#define GPIOC_BASE_ADDR     (0x4000E400U)                             /* GPIOC基地址 */
#define GPIOD_BASE_ADDR     (0x4000E600U)                             /* GPIOD基地址 */
#define GPIOE_BASE_ADDR     (0x4000E800U)                             /* GPIOE基地址 */

/* 获取端口基地址宏 */
#define GET_PORT_BASE_ADDR(port) GPIO##port##_BASE_ADDR

/*
    - 计算全局引脚编号
    - IM94x每个GPIO端口间隔0x200字节, 每个端口18个引脚
    - 例如: PA0编号为0，PB2编号为18
    - 使用方式:
        PA8: uint32_t pin_num = GET_PIN_NUM(A, 8);
*/
#define GET_PIN_NUM(PORTx, PIN)                                                                            \
    ((PIN) < PORT_PIN_MAX_SIZE ? (uint32_t)((PORT_PIN_MAX_SIZE * (((uint32_t)GET_PORT_BASE_ADDR(PORTx) -   \
                                                                   (uint32_t)GPIOA_BASE_ADDR) /            \
                                                                  PORT_ADDR_INTERVAL)) +                   \
                                            (PIN))                                                         \
                               : 0xFFFFFFFF)

/**
 * @brief GPIO引脚模式枚举
 *
 */
typedef enum
{
    DRV_GPIO_PIN_MODE_HIZ             = 0U, /*!< 高阻态 */
    DRV_GPIO_PIN_MODE_OUTPUT          = 1U, /*!< 输出模式 */
    DRV_GPIO_PIN_MODE_INPUT_FLOATING  = 2U, /*!< 浮空输入 */
    DRV_GPIO_PIN_MODE_INPUT_PULL_UP   = 3U, /*!< 上拉输入 */
    DRV_GPIO_PIN_MODE_INPUT_PULL_DOWN = 4U, /*!< 下拉输入 */
} snf_gpio_pin_mode_e;

/**
 * @brief GPIO引脚中断触发条件配置
 *
 */
typedef enum
{
    DRV_GPIO_PIN_INT_DISABLED     = 0U, /*!< 外部中断请求已被禁用。 */
    DRV_GPIO_PIN_INT_RISING_EDGE  = 1U, /*!< 上升沿触发外部中断 */
    DRV_GPIO_PIN_INT_FALLING_EDGE = 2U, /*!< 下降沿触发外部中断 */
    DRV_GPIO_PIN_INT_BOTH_EDGE    = 3U  /*!< 双边沿触发外部中断 */
} snf_gpio_pin_interrupt_e;

/**
 * @brief GPIO引脚电平枚举
 *
 */
typedef enum
{
    DRV_GPIO_PIN_LEVEL_LOW  = 0U, /*!< 低电平 */
    DRV_GPIO_PIN_LEVEL_HIGH = 1U  /*!< 高电平 */
} snf_gpio_pin_level_e;

/**
 * @brief GPIO引脚配置结构体
 *
 */
typedef struct
{
    uint32_t                 pin_num;          /*!< 引脚编号, 通过GET_PIN_NUM宏获取, 用于计算PORTx和PINx */
    snf_gpio_pin_mode_e      mode;             /*!< 引脚模式 */
    snf_gpio_pin_interrupt_e interrupt_config; /*!< 引脚中断配置 */
    snf_gpio_pin_level_e     init_level;       /*!< 引脚初始电平 */
} snf_gpio_config_t;

result_e snf_drv_gpio_init(const snf_gpio_config_t *gpio_config);
result_e snf_drv_gpio_write_pin(uint32_t pin_num, snf_gpio_pin_level_e level);
result_e snf_drv_gpio_read_pin(uint32_t pin_num, snf_gpio_pin_level_e *level);
result_e snf_drv_gpio_set_pin_mode(uint32_t pin_num, snf_gpio_pin_mode_e mode);

#endif
